Ett Listigt
Volume Number: 7
Issue Number: 8
Column Tag: Programmer's Forum
Ett Listigt Program 
By Martin Minow, Arlington, MA
Perhaps I must begin with an apology for the title. It’s Swedish, and translates
to “a clever program.” which is a bit of an overstatement for a minor hack but I
couldn’t resist the opportunity to make a bilingual pun.
The program, in fact, isn’t clever at all. It merely serves to demonstrate how
you can take control of the way the List Manager draws your data.
The List Manager, described in Inside Mac, volume IV, is a very simple table
construction and selection function that lets your program manage a small collection of
data. I use it in a number of applications: for example, to store the phone numbers for
an autodialer and the names of elite runners in a road race display program.
While the List Manager is simple to use, it has a few limitations. For example,
it is pretty sloppy about how it handles fonts, so if you put a list in a dialog, you run
the risk of displaying parts of the dialog in the list font, rather than the dialog font.
Fortunately, the good folk who designed the List Manager gave programmers a
way to add our own control function. They assume we’ll write the function as a code
resource that is stored in the application’s resource fork. While this works well for
most applications, this article shows two tricks that should make the list definition
function easier to write and debug (no separate code resource) and easier to integrate
into an application. The debugging advantages are significant: it is impossible to use the
Think C symbolic debugger in a separately-compiled code resource.
The List Handler
Ignoring for a moment how we actually get there, the LDEF resource performs
four services for the List Manager:
1. Initialize any private information when the list is first created. The demo
handler defines some information based on the current font.
2. Draw a list cell. If your application doesn’t specify a drawing routine, the demo
handler draws the cell using the font (and size) that were specified when the list
was created. The window’s original font and size are restored, so the list can be
used in, e.g., a dialog without messing up the font/size for other dialog items.
3. Hilite a list cell. The demo handler uses the new method of color highlighting
described in Inside Mac, vol 5, pp 61-62.
4. Close a list -- this call lets a LDEF procedure release any private information.
The demo handler ignores this call since it doesn’t store any private information.
The bulk of the work is done by the draw routine: the pen is moved to the proper
place within the cell, the list data storage handle is locked in memory, the display area
is erased, the font and size are set, and the data drawn (either by the handler or by the
application’s callback function). Finally, the list data handle lock state is restored. If
the cell was selected, the normal highlight procedure is then executed.
With that as background, the only remaining problem is connecting the list
handler to your application. The sample program demonstrates three possible methods:
building a separate code resource, building a fake code resource, and directly installing
the list handler in the ListRecord without a separate resource.
The Code Resource
The approved way to write a list handler is to build it as a separate code resource
that is stored as a LDEF resource in the application’s resource fork. Then, you specify
the number of the LDEF resource when you execute LNew. If you’ve never done this
before, the process is strange, but it’s fairly simple if you take it step-by-step. Using
Think C (version 4), do the following:
1. Create a new project, say LDEF.π.
2. Add the LDEF Resource.c and MacHeaders files.
3. Set the project type to Code Resource, set the resource name to LDEF and the
resource id to, say, 128.
4. Build the code resource, saving it as LDEF.rsrc
Now, build your application. Think C (unfortunately) only supports RMaker, so
you have to add the following line to your RMaker source file:
Include LDEF.rsrc
RMaker will merge the code resource into your application’s resource fork.
Fake LDEF
Instead of building a separate LDEF resource, you can also compile the entire
LDEF into your program. However, in order to satisfy the Macintosh Toolbox standards,
you still need a resource. You can create one on the fly by building a callback LDEF.
You do this by creating a dummy LDEF in your resource file that is defined as follows:
/* 1 */
Type LDEF = GNRL
, 128
.h
4EF9 0000 0000
Then, when your program starts, it calls the SetupLDEF function that “plugs”
the address of the actual function into the LDEF and marks the LDEF as non-purgeable.
As with the “normal” procedure, LNew specifies the resource id (128 in the example),
and the toolbox ListManager manages the resource normally. Hex 4EF9 is a jump
instruction, so the ListManager jumps to the real function. Your application only calls
SetupLDEF once, even if the list handler will be used for several lists.
No Resource Needed
You don’t even need the degenerate 3 word version above. Instead, you can stuff
the function address into the ListRecord after creating the list. While this technique
seems to work without problems, it isn’t blessed by the Mac folk, so don’t complain
when it stops working in some future release. The add_LDEF() function creates the fake
handle -- call it just after you create the list. Be sure to call remove_LDEF() before
deleting the list: otherwise, your program will surely crash!
Which should you use?
Each of the three methods has its own advantages and disadvantages:
• The fully-compiled method is perhaps only useful if you absolutely cannot have a
visible LDEF resource: perhaps for security or anti-viral reasons. Before using
it, you should remember that it isn’t “blessed” by the Macintosh interface
people.
• The “fake- resource” callback method is probably the most useful for
development: you can set breakpoints within the list handler. (By the way, the
“fake- resource” technique is useful for other user-written handlers that the
Toolbox assumes will be stored as resources.) It does require, however, that you